package com.xinqi.modules.sys.menu.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xinqi.common.base.enums.YesNoEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.response.R;
import com.xinqi.common.base.utils.lambda.Lambdas;
import com.xinqi.common.base.utils.tree.Trees;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.mybatis.utils.Queries;
import com.xinqi.common.satoken.utils.LoginHelper;
import com.xinqi.modules.sys.menu.convert.MenuConvert;
import com.xinqi.modules.sys.menu.domain.MenuEntity;
import com.xinqi.modules.sys.menu.dto.req.AddRoleMenuDTO;
import com.xinqi.modules.sys.menu.dto.req.MenuAllQueryDTO;
import com.xinqi.modules.sys.menu.dto.req.MenuCreateDTO;
import com.xinqi.modules.sys.menu.dto.req.MenuDeleteDTO;
import com.xinqi.modules.sys.menu.dto.req.MenuQueryDTO;
import com.xinqi.modules.sys.menu.dto.req.MenuTreeDTO;
import com.xinqi.modules.sys.menu.dto.req.MenuUpdateDTO;
import com.xinqi.modules.sys.menu.dto.rsp.MenuResultDTO;
import com.xinqi.modules.sys.menu.manager.MenuManager;
import com.xinqi.modules.sys.menu.service.MenuService;
import com.xinqi.modules.sys.menu.service.RoleMenuService;
import com.xinqi.modules.user.user.client.UserClient;
import com.xinqi.modules.user.user.dto.rsp.UserResultDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 系统菜单服务层实现
 *
 * @author: linkai
 * @date: 2023/04/01
 */
@Validated
@Service("menuService")
@RequiredArgsConstructor
public class MenuServiceImpl implements MenuService {

    private final MenuConvert menuConvert;

    private final MenuManager menuManager;

    private final RoleMenuService roleMenuService;

    private final UserClient userClient;

    /**
     * 分页查询 系统菜单数据
     */
    @Override
    @DS("slaver")
    public PageInfo<MenuResultDTO> page(Param pageable, MenuQueryDTO query) {
        IPage<MenuEntity> page = menuManager.page(Pages.page(pageable), wrapper(query));
        return Pages.convert(page, menuConvert::convert);
    }

    /**
     * 查询 系统菜单数据
     */
    @Override
    public List<MenuResultDTO> find(MenuQueryDTO query) {
        return menuManager.list(wrapper(query)).stream()
            .map(menuConvert::convert).collect(Collectors.toList());
    }

    private LambdaQueryWrapper<MenuEntity> wrapper(MenuQueryDTO query) {
        LambdaQueryWrapper<MenuEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(MenuEntity::getId, v));
        Queries.accept(query.getName(), v -> wrapper.like(MenuEntity::getName, v));
        return wrapper;
    }

    /**
     * 根据id查询 系统菜单数据
     */
    @Override
    public MenuResultDTO findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return Optional.ofNullable(menuManager.findById(id)).map(menuConvert::convert).orElse(null);
    }

    /**
     * 新增 系统菜单数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(@Valid MenuCreateDTO dto) {
        MenuEntity entity = menuConvert.create(dto);
        menuManager.save(entity);
        return entity.getId();
    }

    /**
     * 根据id修改 系统菜单数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(@Valid MenuUpdateDTO dto) {
        Optional.ofNullable(menuManager.getById(dto.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));
        MenuEntity entity = menuConvert.update(dto);
        return menuManager.updateById(entity);
    }

    /**
     * 根据id删除 系统菜单数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return menuManager.removeById(id);
    }

    /**
     * 根据id删除 系统菜单数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(MenuDeleteDTO dto) {
        return deleteById(dto.getId());
    }

    /**
     * 通过父菜单查询子菜单列表
     */
    @Override
    public List<MenuResultDTO> findTree(@Valid MenuTreeDTO form) {
        LambdaQueryWrapper<MenuEntity> queryWrapper = new LambdaQueryWrapper<>();
        Lambdas.accept(form.getParentId(), v -> queryWrapper.eq(MenuEntity::getParentId, v));
        List<MenuEntity> syMenus = menuManager.list(queryWrapper);
        List<MenuResultDTO> list = syMenus.stream().map(menuConvert::convert).collect(Collectors.toList());
        Long parentId = form.getParentId();
        if (parentId == null) {
            parentId = 0L;
        }
        return Trees.tree(list, parentId);
    }

    @Override
    public List<MenuResultDTO> findAll(@Valid MenuAllQueryDTO dto) {
        return menuManager.findAll(dto);
    }

    @Override
    public List<MenuResultDTO> findChildByParentId(Long parentId) {
        return menuManager.findChildByParentId(parentId);
    }

    @Override
    public List<Long> findAllIds(@Valid MenuAllQueryDTO dto) {
        return menuManager.findAllIds(dto);
    }

    @Override
    public List<MenuResultDTO> findUserMenu(Long userId) {
        UserResultDTO user = R.as(userClient.findById(userId));
        if (Objects.equals(YesNoEnum.YES.ordinal(), user.getIsSuperAdmin())) {
            return this.find(new MenuQueryDTO());
        }
        MenuAllQueryDTO dto = new MenuAllQueryDTO();
        dto.setUserId(userId);
        return menuManager.findUserMenu(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addRoleMenu(AddRoleMenuDTO dto) {
        roleMenuService.addRoleMenu(dto);
        return true;
    }

    @Override
    public List<MenuResultDTO> getRoleMenu(Long roleId) {
        return roleMenuService.findRoleMenu(roleId);
    }

    @Override
    public List<MenuResultDTO> findCurrentUserMenu() {
        UserResultDTO user = R.as(userClient.findById(LoginHelper.getUserId()));
        if (user == null) {
            throw CommonErrors.BAD_REQUEST.asException("用户不存在");
        }
        if (Objects.equals(YesNoEnum.YES.ordinal(), user.getIsSuperAdmin())) {
            return this.find(new MenuQueryDTO());
        }
        return findUserMenu(user.getId());
    }
}
